import { createRouter, createWebHistory } from 'vue-router'

// 指定目录查找vue文件，并以vue文件命名作为菜单的路由链接
const getDynamicRoutes = (menus) => {
  // 指定@/views/pages目录下所有的vue文件（/**/*.vue表示任意文件夹下的任意vue文件）
  const files = import.meta.glob('@/views/pages/**/*.vue', { eager: true })
  // 弄一个空对象，备用
  const Maps = {}
  // 循环遍历我们查找到的所有文件对象，获得所有文件的目录字符串
  Object.keys(files).forEach((key) => {
    // 因为@/views/pages是固定的长度，所以截取从16截取到倒数第四位前面一个字符，就是我们的路由地址和code了,例如/system/menus
    const menuCode = key.slice(16, -10).toLowerCase()
    Maps[menuCode] = files[key].default
  })
  const path = {}
  // 然后根据规则，生成我们的路由对象即可，具体规则根据实际情况来，下面的代码是当前项目的，其他项目可以复制过去慢慢改
  return menus
    .filter((it) => {
      const r = !path[it.code] && Maps[it.code]
      path[it.href] = true
      return r
    })
    .map((it) => {
      return {
        path: it.href,
        name: it.code,
        meta: {
          title: it.name,
          active: it.code,
          hasCache: it.hasCache,
          sort: it.sort
        },
        component: Maps[it.code]
      }
    })
}

// vue-router新版写法变了，不能用 * 通配符匹配未定义的路由了，新版写法如下
const errorRoutes = [
  {
    path: '/404',
    name: '404',
    component: () => import('../frame-pages/error/404.vue'),
    meta: {
      cache: false,
      title: '404'
    }
  },
  {
    path: '/:pathMatch(.*)',
    redirect: '/404'
  }
]

// 动态添加路由的方法，如下，核心为addRoute，其中root是我们父级路由的name，我们指定将路由挂载到某个路由的children里面
const resetRoutes = (menus, errorRoutes = []) => {
  const routes = [...getDynamicRoutes(menus), ...errorRoutes]
  routes.forEach((item) => {
    router.addRoute('root', item) // 与根节点的菜单name
  })
}

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/auth',
      name: 'auth',
      meta: { title: '登录' },
      component: () => import('../frame-pages/Auth.vue')
    },
    {
      path: '/',
      name: 'root',
      meta: { title: '首页' },
      component: () => import('@/views/Index.vue'),
      children: [
        {
          path: '/',
          name: '/',
          component: () => import('@/views/pages/home/index.vue'),
          meta: {
            cache: true,
            title: '首页'
          }
        }
      ]
    }
  ]
})

router.beforeEach(async (to, from, next) => {
  /*
   * 登录页规则：
   * 如果我去登录页，我先看我是否有token，有token的情况下不能去登录页，不然会出现顶号的情况
   * 有token则重定向回去到之前的页面
   * */
  if (to.path === '/auth') {
    if (localStorage.getItem(import.meta.env.VITE_APP_TOKEN_NAME)) {
      await next({ ...from })
    } else {
      await next()
    }
  } else {
    /*
     * 内容页面规则：
     * 首先看我有没有token，至于token是否过期，在请求拦截判断，路由拦截仅判断是否存在
     * 没token的直接去登录页，没token就完全等于没登录，是否有用户信息和token无关，token才是令牌钥匙
     * 有token的话看有无用户信息和菜单信息，没有就查接口，有就不查
     * */
    if (localStorage.getItem(import.meta.env.VITE_APP_TOKEN_NAME)) {
      if (window.$user && window.$menus) {
        const trackData = {
          to: to.fullPath,
          name: to?.meta?.title,
          from: from.fullPath,
          fromName: from?.meta?.title
        }
        window.$apis.track(trackData)
        if (from?.query?.redirect) {
          if (to.path === from.query.redirect) {
            await next()
          } else {
            await next({ path: from?.query?.redirect, replace: true })
          }
        } else {
          await next()
        }
      } else {
        // await binaryToBlob({ fileName: 'template', end: '.jpg', api: 'download' })
        // 注意将数据赋值给window对象下的$user和$menus
        window.$user = await window.$apis.getUserInfo('00000001') // 此处替换成自己需求的获取用户信息接口
        window.$menus = await window.$apis.getMenus() // 此处替换成自己需求的获取菜单列表接口
        resetRoutes(window.$menus, errorRoutes)
        if (from?.query?.redirect) {
          await next({ path: from.query.redirect, replace: true })
        } else {
          await next({ ...to, replace: true })
        }
      }
    } else {
      await next({ path: '/auth', query: { redirect: from.fullPath }, replace: true })
    }
  }
})

export default router
